package pers.qianyu.module.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import pers.qianyu.module.core.comm.Pagination;
import pers.qianyu.module.core.domain.system.converter.SysRoleConverter;
import pers.qianyu.module.core.domain.system.converter.SysUserConverter;
import pers.qianyu.module.core.domain.system.dto.SysUserRoleDTO;
import pers.qianyu.module.core.domain.system.entity.SysRolePO;
import pers.qianyu.module.core.domain.system.entity.SysUserPO;
import pers.qianyu.module.core.domain.system.entity.SysUserRolePO;
import pers.qianyu.module.core.domain.system.query.SysUserRoleQuery;
import pers.qianyu.module.core.domain.system.vo.SysRoleVO;
import pers.qianyu.module.core.domain.system.vo.SysUserVO;
import pers.qianyu.module.system.dao.SysRoleDao;
import pers.qianyu.module.system.dao.SysUserDao;
import pers.qianyu.module.system.dao.SysUserRoleDao;
import pers.qianyu.module.system.exception.SysErrorCodeEnum;
import pers.qianyu.module.system.exception.SysException;
import pers.qianyu.module.system.listener.events.SysUserInfoUpdatedEvent;
import pers.qianyu.module.system.service.SysUserRoleService;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author mizzle rain
 * @date 2020-11-13 12:21
 */
@Service("sysUserRoleService")
public class SysUserRoleServiceImpl
        extends ServiceImpl<SysUserRoleDao, SysUserRolePO>
        implements SysUserRoleService {
    @Autowired
    private SysUserRoleDao sysUserRoleDao;
    @Autowired
    private SysRoleConverter sysRoleConverter;
    @Autowired
    private SysRoleDao sysRoleDao;
    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private SysUserConverter sysUserConverter;
    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public List<SysRoleVO> queryByUserId(Long userId) {
        QueryWrapper<SysUserRolePO> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        List<SysUserRolePO> sysUserRolePOS = sysUserRoleDao.selectList(wrapper);
        Set<Long> roleIds = Optional.ofNullable(sysUserRolePOS)
                .map(List::stream)
                .orElseGet(Stream::empty)
                .map(SysUserRolePO::getRoleId)
                .collect(Collectors.toSet());
        List<SysRolePO> sysRolePOS = CollUtil.isNotEmpty(roleIds) ? sysRoleDao.selectBatchIds(roleIds) : new ArrayList<>();
        return sysRoleConverter.convertToVOS(sysRolePOS);
    }

    @Override
    public void insUserRole(SysUserRoleDTO sysUserRoleDTO) {
        SysUserRolePO sysUserRolePO = new SysUserRolePO();
        sysUserRolePO.setUserId(sysUserRoleDTO.getUserId());
        sysUserRolePO.setRoleId(sysUserRoleDTO.getRoleId());
        if (Objects.isNull(sysUserRoleDao.selectOne(new QueryWrapper<>(sysUserRolePO)))) {
            sysUserRoleDao.insert(sysUserRolePO);
        }
        // 更新Redis
        applicationContext.publishEvent(new SysUserInfoUpdatedEvent(this, sysUserRoleDTO.getUserId()));
    }

    @Override
    public void delAuthUserRole(SysUserRoleDTO sysUserRoleDTO) {
        SysUserRolePO sysUserRolePO = new SysUserRolePO();
        sysUserRolePO.setUserId(sysUserRoleDTO.getUserId());
        sysUserRolePO.setRoleId(sysUserRoleDTO.getRoleId());
        QueryWrapper<SysUserRolePO> wrapper = new QueryWrapper<>(sysUserRolePO);
        int row = sysUserRoleDao.delete(wrapper);
        if (row < 1) {
            throw new SysException(SysErrorCodeEnum.INVALID_PARAMETERS);
        }
        // 更新Redis
        applicationContext.publishEvent(new SysUserInfoUpdatedEvent(this, sysUserRoleDTO.getUserId()));
    }

    @Override
    public Pagination<SysUserVO> queryByRoleId(SysUserRoleQuery query) {
        Page<SysUserRolePO> page = new Page<>(query.getPage(), query.getLimit());
        QueryWrapper<SysUserRolePO> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", query.getRoleId());
        Page<SysUserRolePO> authUserRolePOPage = sysUserRoleDao.selectPage(page, wrapper);
        if (CollUtil.isEmpty(authUserRolePOPage.getRecords())) {
            throw new SysException(SysErrorCodeEnum.INVALID_SYS_ROLE_ID);
        }

        Pagination<SysUserVO> pagination = new Pagination<>();
        pagination.setCurrent(authUserRolePOPage.getCurrent());
        pagination.setTotal(authUserRolePOPage.getTotal());
        pagination.setSize(authUserRolePOPage.getSize());
        List<Long> userIds = Optional.ofNullable(authUserRolePOPage.getRecords())
                .map(List::stream)
                .orElseGet(Stream::empty)
                .map(SysUserRolePO::getUserId)
                .collect(Collectors.toList());
        List<SysUserPO> sysUserPOS = CollUtil.isNotEmpty(userIds) ? sysUserDao.selectBatchIds(userIds) : new ArrayList<>();
        pagination.setRecords(Optional.ofNullable(sysUserPOS)
                .map(List::stream)
                .orElseGet(Stream::empty)
                .map(sysUserConverter::convertToVO)
                .collect(Collectors.toList()));
        return pagination;
    }


}
